#pragma once
#include <unordered_map>
#include "Camera.h"
#include "matrix.h"


namespace FIRSTDX
{
	inline bool	IsKeyDown	(int virtualKey)
	{
		return (::GetAsyncKeyState(virtualKey) & 0x8000) == 0x8000;
	}

	inline bool	IsKeyUp	(int virtualKey)
	{
		return (::GetAsyncKeyState(virtualKey) & 0x8000) != 0x8000;
	}


	struct vector2
	{
		float x,y;// TODO move this to its own header.
		vector2():x(0),y(0){}
		vector2(float _x, float _y):x(_x),y(_y){}
	};
	class Mouse
	{
	public:
		typedef unsigned int ButtonId;
		Mouse( HWND hwnd);
		unsigned int getNumButtons() const;
		vector2 getPosition() const;
		bool didGoUp( ButtonId button) const;
		bool didGoDown( ButtonId button ) const;
		bool isDown( ButtonId button ) const;

		void updateState();//TODO remove if unneeded
		void ProcessMessages(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
	private:
		static const UINT MAX_BUTTONS = 3;
		HWND m_hWnd;
		bool m_buttonStates[ MAX_BUTTONS ];		// true is down
		bool m_lastButtonStates[ MAX_BUTTONS ];
	};

	Mouse& GetTheMouse(HWND hWnd = NULL);

	class InputController
	{
	public:
		static void update(Camera& camera)
		{
			if (IsKeyDown('P'))
			{
				trigger = trigger==1?0:1;
				POINT mousePos;
				::GetCursorPos(&mousePos);
				MOUSE_X = mousePos.x;
				MOUSE_Y = mousePos.y;
			}

			if(trigger == 1)//'P' to trigger
				return;

			const float KEY_BOARD_IMPULSE_SCALAR = 0.1f;
			vec3f modelImpuse(0,0,0);

			static const int coord_dir = -1;
	

			if(IsKeyDown('W'))
			{
				modelImpuse.z -= KEY_BOARD_IMPULSE_SCALAR * coord_dir;
			}
			if(IsKeyDown('S'))
			{
				modelImpuse.z += KEY_BOARD_IMPULSE_SCALAR * coord_dir;
			}
			if(IsKeyDown('A'))
			{
				modelImpuse.x -= KEY_BOARD_IMPULSE_SCALAR;
			}
			if(IsKeyDown('D'))
			{
				modelImpuse.x += KEY_BOARD_IMPULSE_SCALAR;
			}
			if(IsKeyDown(VK_SPACE))
			{
				modelImpuse.y += KEY_BOARD_IMPULSE_SCALAR;
			}
			if(IsKeyDown(VK_CONTROL) || IsKeyDown('C'))
			{
				modelImpuse.y -= KEY_BOARD_IMPULSE_SCALAR;
			}
			camera.applyImpulse(modelImpuse);

			//rotate the camera

			POINT mousePos;
			::GetCursorPos(&mousePos);

			//how fast did the mouse move?

			const float MOUSE_ROTATION_SCALAR =  0.1f ;
			vec3f mouseDelta( MOUSE_ROTATION_SCALAR * (mousePos.y-MOUSE_Y),
				MOUSE_ROTATION_SCALAR * (mousePos.x-MOUSE_X),0);

			camera.rotate(mouseDelta);
			//re-center the mouse
 
			//trace(camera.getRotation().x<<","<<camera.getRotation().y<<","<<camera.getRotation().z);
			//::SetCursorPos(MOUSE_X,MOUSE_Y);
			MOUSE_X = mousePos.x;
			MOUSE_Y = mousePos.y;

			//if key up, reset the keyMap value
			std::unordered_map<int,bool>::iterator it = keyMap.begin();
			while (it!= keyMap.end())
			{
				if (IsKeyUp(it->first))
				{
					it->second = false;
				}
				++it;
			}
		}

		static void setRect(LONG _X, LONG _Y)
		{
			MOUSE_X = _X;
			MOUSE_Y = _Y;
		}

		static bool getKeyMap(int key)
		{
			return keyMap[key];
		}

		static void setKeyMap(int f, bool s)
		{
			keyMap[f] = s;
		}
	private:
		static LONG MOUSE_X,MOUSE_Y;
		static std::unordered_map<int, bool> keyMap; 
		static int trigger;
	};

	void calculateCenter(HWND hwnd);

}